package com.blue.wechat.invoke.spi;

import java.text.MessageFormat;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blue.http.client.HttpInvoker;
import com.blue.wechat.cache.JsApiTicketCache;
import com.blue.wechat.cache.Wechat;
import com.blue.wechat.cache.WechatCache;
import com.blue.wechat.invoke.InvokeException;
import com.blue.wechat.invoke.Invoker;
import com.blue.wechat.invoke.WechatContainer;
import com.blue.wechat.invoke.WechatInvokeUtil;
import com.blue.wechat.invoke.WechatInvoker;
import com.blue.wechat.invoke.annotation.WechatUrl;
import com.blue.wechat.invoke.model.AccessToken;
import com.blue.wechat.invoke.model.JsApiTicket;

/**
 * 接口授权
 * 
 * @author zhengj
 * @since 1.0 2017年1月25日
 */
@WechatUrl(WechatInvoker.JS_API_TICKET)
public class JsApiTicketInvoker implements Invoker<JsApiTicket>
{
	private static Logger logger = LoggerFactory.getLogger(JsApiTicketInvoker.class);
	private static final WechatInvoker INVOKER = WechatInvoker.JS_API_TICKET;
	public static final int EXPIRE = 900; // 检查过期时间
	
	@Resource
	private WechatContainer wechatContainer;
	@Resource
	private HttpInvoker httpInvoker;
	@Resource
	private JsApiTicketCache jsApiTicketCache;
	@Resource
	private WechatCache wechatCache;
	
	public JsApiTicketInvoker()
	{
	}

	@Override
	public JsApiTicket invoke(String code, Object post, String... get) throws InvokeException
	{
		Wechat wechat = wechatCache.getByCode(code);
		if (wechat == null)
			throw InvokeException.getException(InvokeException.WECHAT_NOT_FOUND + code);
		
		JsApiTicket ticket = jsApiTicketCache.getByCode(code);
		int expire = jsApiTicketCache.expire(code);
		if (ticket != null && expire > EXPIRE)
			return ticket;
		
		if (jsApiTicketCache.lock(code))
		{
			ticket = jsApiTicketCache.getByCode(code);
			expire = jsApiTicketCache.expire(code);
			if (ticket != null && expire > EXPIRE)
				return ticket;
			try
			{
				return this.invoke(wechat);
			}
			finally
			{
				jsApiTicketCache.unlock(code);
			}
		}
		else
		{
			return this.invoke(wechat);
		}
	}

	private JsApiTicket invoke(Wechat wechat)
	{
		AccessToken token = wechatContainer.invoke(wechat.getCode(), WechatInvoker.ACCESS_TOKEN, null);
		
		String url = MessageFormat.format(INVOKER.getUrl(), token.getAccessToken());
		String resp = null;
		long start = System.currentTimeMillis();
		try
		{
			resp = httpInvoker.get(url);
			JsApiTicket ticket = WechatInvokeUtil.toResponse(resp, JsApiTicket.class);
			logger.info("微信[code={}] js-api-ticket：{}", wechat.getCode(), ticket.getTicket());
			jsApiTicketCache.update(wechat.getCode(), ticket);
			WechatInvokeUtil.log(wechat.getName(), INVOKER.getName(), url, null, null, (int)(System.currentTimeMillis() - start), resp, null);
			return ticket;
		}
		catch (Exception e)
		{
			WechatInvokeUtil.log(wechat.getName(), INVOKER.getName(), url, null, null, (int)(System.currentTimeMillis() - start), e.getMessage(), e);
			throw InvokeException.getException(InvokeException.WECHAT_JS_API_TICKET_ERROR);
		}
	}
}
